/** @file        rgb565bmp.c
  * @brief       将原始的RGB565图像转化为BMP的标准格式
  * @details   
  * @author      皓瑞
  * @date        2021-03-16
  * @version     V1.0
  * @copyright   
  **********************************************************************************
  * @attention
  **********************************************************************************
*/


#include "baiduyun/rgb565bmp.h"

using namespace std;


namespace Rgb565Bmp{


string rgb565Bmp(const char* image, long width, long height)
{
    long file_size;                          // 文件的大小
    long data_size;                          // 数据的大小
    long widthAlignBytes;                    // 宽度对其字节长度
                                             // 可能不等于width
    string  result;                          // 存储结果

    // BMP文件头
    unsigned char header[66] = {
        // BITMAPFILEINFO
        'B', 'M',               // [0-1] bfType:必须是BM字符
        0, 0, 0, 0,             // [2-5] bfSize:总文件大小
        0, 0, 0, 0,             // [6-9] brReserved1,bfReserved2:保留
        sizeof(header), 0, 0, 0,// [10-13] bfOffBits:到图像数据的偏移
        // BITMAPFILEHEADER
        0x28, 0, 0, 0,          // [14-17] biSize:BITMAPINFOHEADER大小40字节
        0, 0, 0, 0,             // [18-21] biWidth:图片宽度
        0, 0, 0, 0,             // [22-25] biHeight:图片高度
        0x01, 0,                // [26-27] biPlanes:必须为1
        0x10, 0,                // [28-29] biBitCount:16位
        0x03, 0, 0, 0,          // [30-33] biCompression:BI_BITFIELDS=3
        0, 0, 0, 0,             // [34-37] biSizeImage:图片大小
        0x12, 0x0B, 0, 0,       // [38-41] biXPelsPerMeter:单位长度内的像素数
        0x12, 0x0B, 0, 0,       // [42-45] biYPelsPerMeter:单位长度内的像素数
        0, 0, 0, 0,             // [46-49] biClrUsed:可用像素数，设为0即可
        0, 0, 0, 0,             // [50-53] biClrImportant:重要颜色数，设为0即可
        // RGBQUAD MASK
        0x0, 0xF8, 0, 0,        // [54-57] 红色掩码
        0xE0, 0x07, 0, 0,       // [58-61] 绿色掩码
        0x1F, 0, 0, 0           // [62-65] 蓝色掩码
    };

    widthAlignBytes = (width * 16 + 31)/32 * 4;        // 每行需要的合适字节个数 (1字=4字节)
    data_size = widthAlignBytes * height;              // 图像数据大小
    file_size = data_size + sizeof(header);            // 整个文件的大小
    result.reserve(file_size);                         // 预分配内存

    /*! 使用指针修改文件头部分信息 */
    *((long*)(header + 2)) = file_size;
    *((long*)(header + 18)) = width;
    *((long*)(header + 22)) = height;
    *((long*)(header + 34)) = data_size;
    
    /*! 写入文件头部 */
    result.append((const char*)header, sizeof(char)*sizeof(header));
    
    /*! 如果刚好宽度是四字节对齐的 */
    if(widthAlignBytes == width * 2){
        result.append(image, sizeof(char)*data_size);
    // 每一行单独写入
    }else{
        for(int i=0; i<height; i++){
          static char buf[4] = {0, 0, 0, 0};
          result.append(image + i*width*2, sizeof(unsigned)*width*2);
          result.append(buf, sizeof(unsigned)*widthAlignBytes-width*2);
        }
    }

    return result;
}

}